查看原文
其他

Win10 1909逆向(反向计算Windows内核内存布局及代码实现)

学技术打豆豆 看雪学院 2021-03-06

本文为看雪论坛优秀文章

看雪论坛作者ID:学技术打豆豆





0x0 前言


在最新的Windows版本中,内存动态并且很多在32位下的变量符号,Windbg现如今都没有了,变成了类似qword_1404687D8这样的东西,对于逆向内存的同学来说,非常不便,但是Windows为了提高效率来进行地址判断的前提下还是给我们留下了一条门缝,我们可以利用此机制反向推导出一些重要的内存布局。





0x1  演示

         


注1:最下面的两个地址是特意申请的两个地址,分别是非分页内存和分页内存地址,用来和上面的基址来比较。


注2:MMPFNDATABASE的基址对比正确。


注3:MiVaProcessSpace 是动态内核虚拟地址空间。





0x2 原理


Windows在内存设计之初,设计了一个内核Mark标记,从0xFFFF8000 0000 0000起一直标记了0x100个的标记,这里被微软根据特定的位算法进行了特别的划分(代码演示)。


其内核内存标记如下:



那这些数字代表什么意义?微软其实已经定了一个枚举类型来详细记录:



那通过这两个我们就可以反推出我们需要的内存布局(有些内存布局在这里无法得到,是因为有额外的处理流程,可以通过别的方法得到)。





0x3 简单代码实现


#include <ntddk.h> #define NameSize 0x10#define MiVaUnused 0#define MiVaSessionSpace 1#define MiVaProcessSpace 2#define MiVaBootLoaded 3#define MiVaPfnDatabase 4#define MiVaNonPagedPool 5#define MiVaPagedPool 6#define MiVaSpecialPoolPaged 7#define MiVaSystemCache 8#define MiVaSystemPtes 9#define MiVaHal 10#define MiVaSessionGlobalSpace 11#define MiVaDriverImages 12#define MiVaSystemPtesLarge 13#define MiVaKernelStacks 14#define MiVaMaximumType 15 PCHAR TypeName[NameSize] ={ "MiVaUnused", "MiVaSessionSpace", "MiVaProcessSpace", "MiVaBootLoaded", "MiVaPfnDatabase", "MiVaNonPagedPool", "MiVaPagedPool", "MiVaSpecialPoolPaged", "MiVaSystemCache", "MiVaSystemPtes", "MiVaHal", "MiVaSessionGlobalSpace", "MiVaDriverImages", "MiVaSystemPtesLarge", "MiVaKernelStacks", "MiVaMaximumType"}; PVOID FindBase();PVOID FindSystemKernenlRegion(PVOID pMark);PVOID FindBaseRegion(PVOID pMark, UCHAR Type);VOID Unload(PDRIVER_OBJECT pDriverObject){ KdPrint(("end\n")); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath){ KdPrint(("start\n")); pDriverObject->DriverUnload = Unload; //第一步找到Mark地址 PVOID pMarkAddr = FindBase(); //第二步开始解析 FindSystemKernenlRegion(pMarkAddr); PVOID NonPool = ExAllocatePoolWithTag(NonPagedPool, 0x1000, 'NonP'); PVOID Pool = ExAllocatePoolWithTag(PagedPool, 0x1000, 'ionP'); KdPrint(("NonPagePool=%llx", NonPool)); KdPrint(("PagePool=%llx", Pool)); ExFreePool(NonPool); ExFreePool(Pool); return STATUS_SUCCESS;} PVOID FindBase(){ UNICODE_STRING FuncName; RtlInitUnicodeString(&FuncName, L"ExAcquirePushLockExclusiveEx"); PVOID FuncAddr=MmGetSystemRoutineAddress(&FuncName); PUCHAR var = (PUCHAR)FuncAddr; for (int i = 0; i < 0x100; i++) { if (*var == 0x48 && *(var+3)==0x27) { return var+(*(PUINT32)(var - 4)); } var++; } return 0;}PVOID FindSystemKernenlRegion(PVOID pMark){ PVOID Region = 0; for (int i = 0; i < 0x10; i++) { KdPrint(("%s=%llx\n", TypeName[i], FindBaseRegion(pMark, i))); } }PVOID FindBaseRegion(PVOID pMark,UCHAR Type){ PUCHAR var = pMark; UINT64 pBaseAddr = 0x100; // for (int i = 0; i < 0x100; i++) { if (*(var) == Type) { pBaseAddr =((pBaseAddr | i) << 0x27 | 0xFFFF000000000000); return pBaseAddr; } var++; } return 0; }





0x4 总结


可以利用点很多,希望能让大家了解一些Windows的内存机制,以后共同学习。




- End -


看雪ID:学技术打豆豆

https://bbs.pediy.com/user-814951.htm

  *本文由看雪论坛 学技术打豆豆 原创,转载请注明来自看雪社区。


推荐文章++++

* 索然无味的勒索病毒

* 初试so文件解密

* 一种枚举系统热键的思路及代码实现(Win7&Win10)

* XposedFridaBridge:使用Frida加载Xposed插件

* TSG CTF 2020 Reverse-ing




好书推荐











公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



ps. 觉得对你有帮助的话,别忘点分享点赞在看,支持看雪哦~


“阅读原文”一起来充电吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存